package org.bitterorange.flansmodslain.listeners;

// import net.minecraft.entity.Entity;
// import net.minecraft.entity.player.EntityPlayer;
// import net.minecraftforge.event.entity.living.LivingDeathEvent;

import com.flansmod.common.PlayerHandler;
import com.flansmod.common.driveables.DriveableType;
import com.flansmod.common.driveables.EntityDriveable;
import com.flansmod.common.driveables.EntityVehicle;
import com.flansmod.common.guns.EntityBullet;
import com.flansmod.common.guns.item.ItemGrenade;
import com.flansmod.common.mob.EntitySoldier;
import com.flansmod.common.mob.api.SoldierAPI;
import com.flansmod.common.teams.Team;
import com.flansmod.common.types.InfoType;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import org.bitterorange.flansmodslain.FlansModAPI;
import org.bitterorange.flansmodslain.models.EntitySoldierWrapper;
import org.bitterorange.flansmodslain.models.PlayerSlainEvent;
import org.bitterorange.flansmodslain.models.SlayType;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftEntity;
import org.bukkit.entity.Player;

import java.util.UUID;
import java.util.logging.Logger;

/**
 * 超级无敌屎山代码，不要试图碰它。
 */
public class PlayerSlainListener {
    public static final Class<?> EntityPlayerClass;
    // private static final Class<?> EntityPlayerMPClass;
    public static final Class<?> LivingDeathEventClass;
    public static final Class<?> DamageSourceClass;
    public static final Class<?> ItemClass;
    public static final Class<?> WorldClass;
    public static final Class<?> EntityLivingBaseClass;
    public static final Class<?> RegistryNamespacedClass;
    public static final Class<?> GameProfileClass;
    public static final Class<?> EntityDamageSourceCollisionClass;
    public static final Class<?> MCHeliEntityAircraftClass;
    public static final Class<?> MCHeliEntityAircraftInfoClass;
    public static final Class<?> FlansModBullet;
    public static final Class<?> FlansModGrenade;
    public static final Class<?> FlansModBulletType;
    public static final Class<?> FlansModGrenadeType;
    static {
        Class<?> entityPlayerClass;
        // Class<?> entityPlayerMPClass;
        Class<?> livingDeathEventClass;
        Class<?> damageSourceClass;
        Class<?> itemClass;
        Class<?> worldClass;
        Class<?> entityLivingBaseClass;
        Class<?> registryNamespacedClass;
        Class<?> gameProfileClass;
        Class<?> entityDamageSourceCollisionClass;
        Class<?> mCHeliEntityAircraft;
        Class<?> mCHeliEntityAircraftInfoClass;
        Class<?> flansModBullet;
        Class<?> flansModGrenade;
        Class<?> flansModBulletType;
        Class<?> flansModGrenadeType;
        try {
            entityPlayerClass = Class.forName("net.minecraft.entity.player.EntityPlayer");
            entityLivingBaseClass = Class.forName("net.minecraft.entity.EntityLivingBase");
            // entityPlayerMPClass = Class.forName("net.minecraft.entity.player.EntityPlayerMP");
            livingDeathEventClass = Class.forName("net.minecraftforge.event.entity.living.LivingDeathEvent");
            damageSourceClass = Class.forName("net.minecraft.util.DamageSource");
            itemClass = Class.forName("net.minecraft.item.Item");
            worldClass = Class.forName("net.minecraft.world.World");
            registryNamespacedClass = Class.forName("net.minecraft.util.RegistryNamespaced");
            gameProfileClass = Class.forName("com.mojang.authlib.GameProfile");
            entityDamageSourceCollisionClass = Class.forName("com.flansmod.common.driveables.EntityDamageSourceCollision");
            mCHeliEntityAircraft = Class.forName("mcheli.aircraft.MCH_EntityAircraft");
            mCHeliEntityAircraftInfoClass = Class.forName("mcheli.aircraft.MCH_AircraftInfo");
            flansModBullet = Class.forName("com.flansmod.common.guns.EntityBullet");
            flansModGrenade = Class.forName("com.flansmod.common.guns.EntityGrenade");
            flansModBulletType = Class.forName("com.flansmod.common.guns.type.BulletType");
            flansModGrenadeType = Class.forName("com.flansmod.common.guns.type.GrenadeType");
            Logger.getGlobal().info("§eFlansModSlain Hook 加载成功！");
        } catch (Exception e) {
            entityPlayerClass = null;
            entityLivingBaseClass = null;
            // entityPlayerMPClass = null;
            livingDeathEventClass = null;
            damageSourceClass = null;
            itemClass = null;
            worldClass = null;
            registryNamespacedClass = null;
            gameProfileClass = null;
            entityDamageSourceCollisionClass = null;
            mCHeliEntityAircraft = null;
            mCHeliEntityAircraftInfoClass = null;
            flansModBullet = null;
            flansModGrenade = null;
            flansModBulletType = null;
            flansModGrenadeType = null;
            Logger.getGlobal().warning("§cFlansModSlain Hook 加载失败！");
            e.printStackTrace();
        }
        EntityPlayerClass = entityPlayerClass;
        EntityLivingBaseClass = entityLivingBaseClass;
        // EntityPlayerMPClass = entityPlayerMPClass;
        LivingDeathEventClass = livingDeathEventClass;
        DamageSourceClass = damageSourceClass;
        ItemClass = itemClass;
        WorldClass = worldClass;
        RegistryNamespacedClass = registryNamespacedClass;
        GameProfileClass = gameProfileClass;
        EntityDamageSourceCollisionClass = entityDamageSourceCollisionClass;
        MCHeliEntityAircraftClass = mCHeliEntityAircraft;
        MCHeliEntityAircraftInfoClass = mCHeliEntityAircraftInfoClass;
        FlansModBullet = flansModBullet;
        FlansModGrenade = flansModGrenade;
        FlansModBulletType = flansModBulletType;
        FlansModGrenadeType = flansModGrenadeType;
    }

    public static void load(){
    }

    // return type: Entity
    private static Object trueDamageSourceEntityAt(Object damageSource) throws Exception {
        return DamageSourceClass.getMethod("func_76346_g").invoke(damageSource);
    }

    // return type: Entity
    private static Object directDamageSourceEntityAt(Object damageSource) throws Exception {
        return DamageSourceClass.getMethod("func_76364_f").invoke(damageSource);
    }

    private static String damageTypeOf(Object damageSource) throws Exception {
        return DamageSourceClass.getMethod("func_76355_l").invoke(damageSource).toString();
    }

    private static String unlocalizedNameOf(Object item) throws Exception {
        return (String) ItemClass.getMethod("func_77658_a").invoke(item);
    }

    /**
     * Forge的EntityPlayer转换为Bukkit的Player对象
     * @param entityPlayer Forge的EntityPlayer对象
     * @return Bukkit的Player对象
     * @throws Exception 反射异常
     */
    private static Player toBukkitPlayer(Object entityPlayer) throws Exception {
        Object gameProfile = EntityPlayerClass.getMethod("func_146103_bH").invoke(entityPlayer);
        UUID uuid = (UUID) GameProfileClass.getMethod("getId").invoke(gameProfile);
        return Bukkit.getPlayer(uuid);
    }

    private static int getIdFromItem(Object item) throws Exception {
        return (int) ItemClass.getMethod("func_150891_b", ItemClass).invoke(null, item);
    }

    private Team teamOfEntityPlayer(Object player) throws Exception {
        return (Team) PlayerHandler.class.getMethod("getPlayerData", EntityPlayerClass).invoke(null,player);
    }


    @EventHandler
    @SubscribeEvent
    public void PlayerDied(net.minecraftforge.event.entity.living.LivingDeathEvent damageEvent) {

        System.out.println("----------------LivingDeathEvent触发----------------" + System.currentTimeMillis());

        Object victimObj = SoldierAPI.getLivingDeathEventVictim(damageEvent);
        Object killerObj = SoldierAPI.getLivingDeathEventKiller(damageEvent);
        Object damageSource = SoldierAPI.getLivingDeathEventDamageSource(damageEvent);
        InfoType wpn = SoldierAPI.getDamageSourceFlanInfoType(SoldierAPI.getLivingDeathEventDamageSource(damageEvent));

        try {
            if (trueDamageSourceEntityAt(damageSource) == null) {
                System.out.println("伤害源为空");
                return;
            }
        } catch (Exception e){
            e.printStackTrace();
        }

        //killer AI
        if(SoldierAPI.isPlayer(victimObj) && SoldierAPI.isSoldier(killerObj)){
            try {
                Player victim = toBukkitPlayer(victimObj);
                EntitySoldierWrapper killer = new EntitySoldierWrapper((EntitySoldier) killerObj);
                Object directSourceEntity = directDamageSourceEntityAt(damageSource);
                Object itemRegistry = ItemClass.getField("field_150901_e").get(null);
                Object item = RegistryNamespacedClass.getMethod("func_82594_a", String.class).invoke(itemRegistry, "flansmod:" + damageTypeOf(damageSource));
                SlayType slayType;
                Material weapon;
                boolean isHeadShot;
                if (directSourceEntity instanceof EntityBullet) {
                    //枪械击杀
                    slayType = SlayType.GUN;
                    EntityBullet entityBullet = (EntityBullet) directSourceEntity;
                    InfoType gunInfoType = entityBullet.firedFrom;
                    isHeadShot = SoldierAPI.getDamageSourceFlanHeadShot(damageSource);
                    if (gunInfoType instanceof DriveableType) {
                        DriveableType driveableType = (DriveableType) gunInfoType;
                        weapon = Material.matchMaterial("flansmod:" + driveableType.shortName);
                    } else {
                        weapon = Material.getMaterial(getIdFromItem(InfoType.class.getField("item").get(gunInfoType)));
                    }

                    System.out.println("AI枪械击杀玩家");

                    Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                            null, victim, slayType, null, isHeadShot,false, weapon, false, true)
                            .setKillerAI(killer));

                } else if (item instanceof ItemGrenade){
                    //榴弹击杀
                    System.out.println("AI榴弹击杀玩家");
                    slayType = SlayType.GRENADE;
                    weapon = Material.matchMaterial("flansmod:" + damageTypeOf(damageSource));
                    Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                            null, victim, slayType, null, false,false, weapon, false, true)
                            .setKillerAI(killer));

                } else {
                    //载具击杀
                    System.out.println("AI载具击杀玩家");
                    if(killer.getVehicle() != null){
                        slayType = SlayType.VEHICLE;
                        Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                null, victim, slayType, "", false,true, Material.AIR, false, true)
                                .setKillerAI(killer));
                    } else {
                        //近战或其他击杀
                        System.out.println("AI近战击杀玩家");
                        slayType = SlayType.VANILLA;
                        String name = SoldierAPI.getHeldItemUnlocalizedName(killerObj);
                        weapon = Material.valueOf(name);
                        Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                null, victim, slayType, null, false,false, weapon, false, true)
                                .setKillerAI(killer));
                    }
                }
            } catch (Exception e){
                e.printStackTrace();
            }
        }

        //killed AI
        else if (SoldierAPI.isSoldier(victimObj) && SoldierAPI.isPlayer(killerObj)){
            try {
                Player killer = toBukkitPlayer(killerObj);
                EntitySoldierWrapper victim = new EntitySoldierWrapper((EntitySoldier) victimObj);
                Object directSourceEntity = directDamageSourceEntityAt(damageSource);
                Object itemRegistry = ItemClass.getField("field_150901_e").get(null);
                Object item = RegistryNamespacedClass.getMethod("func_82594_a", String.class).invoke(itemRegistry, "flansmod:" + damageTypeOf(damageSource));
                SlayType slayType;
                Material weapon;
                boolean isHeadShot;
                if (directSourceEntity instanceof EntityBullet) {
                    //枪械击杀
                    slayType = SlayType.GUN;
                    EntityBullet entityBullet = (EntityBullet) directSourceEntity;
                    InfoType gunInfoType = entityBullet.firedFrom;
                    isHeadShot = SoldierAPI.getDamageSourceFlanHeadShot(damageSource);
                    if (gunInfoType instanceof DriveableType) {
                        DriveableType driveableType = (DriveableType) gunInfoType;
                        weapon = Material.matchMaterial("flansmod:" + driveableType.shortName);
                    } else {
                        weapon = Material.getMaterial(getIdFromItem(InfoType.class.getField("item").get(gunInfoType)));
                    }
                    System.out.println("玩家枪械击杀AI");
                    Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                            killer, null, slayType, null, isHeadShot,false, weapon, true, false)
                            .setKilledAI(victim));

                } else if (item instanceof ItemGrenade){
                    //榴弹击杀
                    System.out.println("玩家榴弹击杀AI");
                    slayType = SlayType.GRENADE;
                    weapon = Material.matchMaterial("flansmod:" + damageTypeOf(damageSource));
                    Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                            killer, null, slayType, null, false,false, weapon, true, false)
                            .setKilledAI(victim));

                } else {
                    //载具击杀
                    if(killer.getVehicle() != null){
                        slayType = SlayType.VEHICLE;
                        System.out.println("玩家载具击杀AI");
                        //flan载具上的枪
                        if(FlansModAPI.isFlanVehicle(killer)) {
                            weapon = Material.matchMaterial("flansmod:" + FlansModAPI.getFlanVehicleShortName(killer));
                            System.out.println("flan" + weapon);
                            slayType = SlayType.GUN;
                            Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                    killer, null, slayType, null, false, false, weapon, true, false)
                                    .setKilledAI(victim));
                        } else { //mch载具逻辑
                            Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                    killer, null, slayType, "", false,true, Material.AIR, true, false)
                                    .setKilledAI(victim));
                        }
                    } else {
                        //近战或其他击杀
                        slayType = SlayType.VANILLA;
                        System.out.println("玩家近战击杀AI");
                        weapon = killer.getItemInHand().getType();
                        Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                killer, null, slayType, null, false,false, weapon, true, false)
                                .setKilledAI(victim));
                    }
                }
            } catch (Exception e){
                e.printStackTrace();
            }
        }

        //both AI
        else if (SoldierAPI.isSoldier(victimObj) && SoldierAPI.isSoldier(killerObj)){
            try {
                EntitySoldierWrapper victim = new EntitySoldierWrapper((EntitySoldier) victimObj);
                EntitySoldierWrapper killer = new EntitySoldierWrapper((EntitySoldier) killerObj);
                Object directSourceEntity = directDamageSourceEntityAt(damageSource);
                Object itemRegistry = ItemClass.getField("field_150901_e").get(null);
                Object item = RegistryNamespacedClass.getMethod("func_82594_a", String.class).invoke(itemRegistry, "flansmod:" + damageTypeOf(damageSource));
                SlayType slayType;
                Material weapon;
                boolean isHeadShot;
                if (directSourceEntity instanceof EntityBullet) {
                    //枪械击杀
                    slayType = SlayType.GUN;
                    EntityBullet entityBullet = (EntityBullet) directSourceEntity;
                    InfoType gunInfoType = entityBullet.firedFrom;
                    isHeadShot = SoldierAPI.getDamageSourceFlanHeadShot(damageSource);
                    if (gunInfoType instanceof DriveableType) {
                        DriveableType driveableType = (DriveableType) gunInfoType;
                        weapon = Material.matchMaterial("flansmod:" + driveableType.shortName);
                    } else {
                        weapon = Material.getMaterial(getIdFromItem(InfoType.class.getField("item").get(gunInfoType)));
                    }
                    System.out.println("AI枪械击杀AI");
                    Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                            null, null, slayType, null, isHeadShot,false, weapon, true, true)
                            .setKilledAI(victim).setKillerAI(killer));

                } else if (item instanceof ItemGrenade){
                    //榴弹击杀
                    slayType = SlayType.GRENADE;
                    System.out.println("AI榴弹击杀AI");
                    weapon = Material.matchMaterial("flansmod:" + damageTypeOf(damageSource));
                    Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                            null, null, slayType, null, false,false, weapon, true, true)
                            .setKilledAI(victim).setKillerAI(killer));

                } else {
                    //载具击杀
                    if(killer.getVehicle() != null){
                        slayType = SlayType.VEHICLE;
                        System.out.println("AI载具击杀AI");
                        Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                null, null, slayType, "", false,true, Material.AIR, true, true)
                                .setKilledAI(victim).setKillerAI(killer));
                    } else {
                        //近战或其他击杀
                        slayType = SlayType.VANILLA;
                        System.out.println("AI近战击杀AI");
                        String name = SoldierAPI.getHeldItemUnlocalizedName(killerObj);
                        weapon = Material.valueOf(name);
                        Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                null, null, slayType, null, false,false, weapon, true, true)
                                .setKilledAI(victim).setKillerAI(killer));
                    }
                }
            } catch (Exception e){
                e.printStackTrace();
            }
        }

        //both Player
        else if(SoldierAPI.isPlayer(victimObj) && SoldierAPI.isPlayer(killerObj)){
            try {
                Player victim = toBukkitPlayer(victimObj);
                Player killer = toBukkitPlayer(killerObj);
                Object directSourceEntity = directDamageSourceEntityAt(damageSource);
                Object itemRegistry = ItemClass.getField("field_150901_e").get(null);
                Object item = RegistryNamespacedClass.getMethod("func_82594_a", String.class).invoke(itemRegistry, "flansmod:" + damageTypeOf(damageSource));
                SlayType slayType;
                Material weapon;
                boolean isHeadShot;
                if (directSourceEntity instanceof EntityBullet) {
                    //枪械击杀
                    slayType = SlayType.GUN;
                    EntityBullet entityBullet = (EntityBullet) directSourceEntity;
                    InfoType gunInfoType = entityBullet.firedFrom;
                    isHeadShot = SoldierAPI.getDamageSourceFlanHeadShot(damageSource);
                    if (gunInfoType instanceof DriveableType) {
                        DriveableType driveableType = (DriveableType) gunInfoType;
                        weapon = Material.matchMaterial("flansmod:" + driveableType.shortName);
                    } else {
                        weapon = Material.getMaterial(getIdFromItem(InfoType.class.getField("item").get(gunInfoType)));
                    }
                    Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                            killer, victim, slayType, null, isHeadShot,false, weapon, false, false));

                } else if (item instanceof ItemGrenade){
                    //榴弹击杀
                    slayType = SlayType.GRENADE;
                    weapon = Material.matchMaterial("flansmod:" + damageTypeOf(damageSource));
                    Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                            killer, victim, slayType, null, false,false, weapon, false, false));

                } else {
                    //载具击杀
                    if(killer.getVehicle() != null){
                        slayType = SlayType.VEHICLE;
                        if(FlansModAPI.isFlanVehicle(killer)) {
                            weapon = Material.matchMaterial("flansmod:" + FlansModAPI.getFlanVehicleShortName(killer));
                            Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                    killer, victim, slayType, null, false,false, weapon, false, false));
                        } else {
                            Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                    killer, victim, slayType, "", false,true, Material.AIR, false, false));
                        }
                    } else {
                        //近战或其他击杀
                        slayType = SlayType.VANILLA;
                        weapon = killer.getItemInHand().getType();
                        Bukkit.getServer().getPluginManager().callEvent(new PlayerSlainEvent(
                                killer, victim, slayType, null, false,false, weapon, false, false));
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }



    }
}
